package game;

import java.awt.event.KeyListener;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

public abstract class AbstractRunnable implements IRenderer
{
    public enum Status
    {
        RUNNING("RUNNING"),STOPPED("STOPPED"),PAUSED("PAUSED"),STARTUP("STARTUP"),PAUSE("PAUSE"),RESUME("RESUME"),RESET("RESET"),SHUTDOWN("SHUTDOWN")
        ;
        private String status;

        private Status(String status)
        {
            this.status = status;
        }
        
        public String getStatus()
        {
            return status;
        }
    }
    
    private String info   = "";
    private Status status = Status.STOPPED;
    
    public synchronized  void setInfo(String info)
    {
        this.info = info;
    }
    
    public synchronized String getInfo()
    {
        return info;
    }
    
    public synchronized  boolean isRunning()
    {
        return status == Status.RUNNING;
    }
    
    public synchronized  boolean isPaused()
    {
        return status == Status.PAUSED;
    }
    
    protected synchronized Status getStatus()
    {
        return status;
    }
    
    public synchronized void setStatus(Status status)
    {
        if (status == getStatus())
        {
            return;
        }
        switch (status)
        {
            case RUNNING:
            {
                switch(getStatus())
                {
                    case RESUME:
                    case STARTUP:
                    {
                        this.status = status;
                        break;
                    }
                    default:
                    {
                        System.out.println("Can not set " + status + " with status " + getStatus());
                        break;
                    }
                }
                break;
            }
            case STOPPED:
            {
                switch(getStatus())
                {
                    case SHUTDOWN:
                    {
                        this.status = status;
                        break;
                    }
                    default:
                    {
                        System.out.println("Can not set " + status + " with status " + getStatus());
                        break;
                    }
                }
                break;
            }
            case PAUSED:
            {
                switch(getStatus())
                {
                    case PAUSE:
                    {
                        this.status = status;
                        break;
                    }
                    default:
                    {
                        System.out.println("Can not set " + status + " with status " + getStatus());
                        break;
                    }
                }
                break;
            }
            case STARTUP:
            {
                switch(getStatus())
                {
                    case RESET:
                    case STOPPED:
                    {
                        this.status = status;
                        start();
                        break;
                    }
                    default:
                    {
                        System.out.println("Can not set " + status + " with status " + getStatus());
                        break;
                    }
                }
                break;
            }
            case PAUSE:
            {
                switch(getStatus())
                {
                    case RUNNING:
                    {
                        this.status = status;
                        pause();
                        break;
                    }
                    default:
                    {
                        System.out.println("Can not set " + status + " with status " + getStatus());
                        break;
                    }
                }
                break;
            }
            case RESET:
            {
                switch(getStatus())
                {
                    case PAUSED:
                    case RUNNING:
                    {
                        this.status = status;
                        reset();
                        break;
                    }
                    default:
                    {
                        System.out.println("Can not set " + status + " with status " + getStatus());
                        break;
                    }
                }
                break;
            }
            case SHUTDOWN:
            {
                switch(getStatus())
                {
                    case PAUSED:
                    case RUNNING:
                    {
                        this.status = status;
                        stop();
                        break;
                    }
                    default:
                    {
                        System.out.println("Can not set " + status + " with status " + getStatus());
                        break;
                    }
                }
                break;
            }
            case RESUME:
            {
                switch(getStatus())
                {
                    case PAUSED:
                    {
                        this.status = status;
                        resume();
                        break;
                    }
                    default:
                    {
                        System.out.println("Can not set " + status + " with status " + getStatus());
                        break;
                    }
                }
                break;
            }
        }
    }
    
    protected synchronized  void start()
    {
        setStatus(Status.RUNNING);
    }
    
    protected synchronized  void stop()
    {
        setStatus(Status.STOPPED);
    }
    
    protected synchronized  void pause()
    {
        setStatus(Status.PAUSED);
    }
    
    protected synchronized  void resume()
    {
        setStatus(Status.RUNNING);
    }
    
    protected synchronized void requestRestart()
    {
        if (getStatus() != Status.STARTUP)
        {
            if (getStatus() == Status.RUNNING || getStatus() == Status.PAUSED)
            {
                setStatus(Status.RESET);
                setStatus(Status.STARTUP);
            }
            else if (getStatus() == Status.STOPPED)
            {
                setStatus(Status.STARTUP);
            }
            setStatus(Status.RUNNING);
        }
    }
    
    protected synchronized  void requestStop()
    {
        if (getStatus() != Status.STOPPED)
        {
            setStatus(Status.SHUTDOWN);
        }
    }
    
    protected abstract void reset();
    
    protected abstract void doNext();
    
    public synchronized final void update()
    {
        if (isRunning() && isPaused() == false)
        {
            doNext();
        }
    }
    
    public KeyListener getKeyboardControl()
    {
        return null;
    }
    
    public MouseListener getMouseControl()
    {
        return null;
    }
    
    public MouseMotionListener getMouseMotionListener()
    {
        return null;
    }
}
